package auth

import auth.User
import org.jsecurity.authc.AuthenticationException
import org.jsecurity.authc.UsernamePasswordToken
import org.apache.commons.codec.digest.DigestUtils
import org.jsecurity.SecurityUtils


import uk.ac.soton.ecs.iam.grid.comms.client.AxisTransport;
import uk.ac.soton.ecs.iam.grid.comms.client.RemoteDataService;
import uk.ac.soton.itinnovation.grid.client.engine.impl.DefaultInvocationEngine;
import uk.ac.soton.itinnovation.grid.client.plugins.GridClientPluginManager;
import uk.ac.soton.itinnovation.grid.client.proxy.HelperProxyFactory;
import uk.ac.soton.itinnovation.grid.client.proxy.InvocationEngineProxyFactory;
import uk.ac.soton.itinnovation.grid.client.proxy.ServiceFactory;
import uk.ac.soton.itinnovation.grid.comms.client.ITInnovSocketFactory;
import uk.ac.soton.itinnovation.grid.comms.client.WSDLCacheImpl;
import uk.ac.soton.itinnovation.grid.comms.client.CertificateFileTrustValidator;
import uk.ac.soton.itinnovation.grid.utils.Identity;
import uk.ac.soton.itinnovation.grid.utils.IdentityProvider;
import uk.ac.soton.itinnovation.grid.utils.KeystoreIdentityProvider;
import uk.ac.soton.itinnovation.grid.utils.UsernameIdentityProvider;


class UserController {
    def jsecSecurityManager

    def index = { 
        redirect(action: 'list', params: params) 
    }
    
    def register = {
        def renderParams = [model:[originalURI:params.originalURI, formData:params, async:request.xhr]]

        if (request.xhr)
            renderParams.template = "registerForm"
        else
            renderParams.view = "register"

        if (request.method == 'POST') {
            def user = User.findByEmail(params.email)
            if (user) {
                renderParams.model.message = "auth.user.already.exists"
                render(renderParams)
            } else {
                if (params.password != params.password2) {
                    renderParams.model.message = "auth.password.mismatch"
                    render(renderParams)
                } else {
                    user = new User(email:params.email, password:(params.password?DigestUtils.shaHex(params.password):null))
                    if (!user.hasErrors() && user.save(flush:true)) {
                        // One can create meta information and add them to the User
                        //def userInfo = new UserInfo(params)
                        //userInfo.user = user
                        //userInfo.save()
                        println "Will call UsernamePasswordToken for ${user.email} and ${user.password}"

                        def authToken = new UsernamePasswordToken(user.email, params.password)
                        this.jsecSecurityManager.login(authToken)

                        if (params.originalURI) {
                            redirect(url:params.originalURI, params:params)
                        } else {
                            redirect(uri:"")
                        }
                    } else {
                        renderParams.model.user = user
                        render(renderParams)
                    }
                }
            }
        } else {
            render(renderParams)
        }
    }
    
    def list = {
        println User.list()
        if(!params.max) params.max = 10
        [ userList: User.list( params ) ]
    }
     
    def create = {
        def user = new User()
        user.properties = params
        return ['user':user]
    }
    
    def save = {
        def user = new User()
        for (roleID in params['roles'])
        {
        println roleID
        user.addToRoles(Role.get(roleID))
        }
        user.password = DigestUtils.shaHex(params['password'])
        user.userName = params['userName']
        user.email = params['email']
        
        //Create the keystore and subjectDN now
        if (user)
            {
                IdentityProvider userIdp;       
                if (user.keystoreLocation == null)
                {
                    String ksDir = grailsApplication.config.gria.identity.keyStoreDir
                    user.keystoreLocation = ksDir + user.userName + ".ks";
                    user.save();
                }
                File keystoreFile = new File(user.keystoreLocation);
                if (!keystoreFile.exists()) {
                    println "Creating Keystore..."
                    KeystoreIdentityProvider issuerIdp = new KeystoreIdentityProvider(
                        grailsApplication.config.gria.identity.issuerKeystore, grailsApplication.config.gria.identity.issuerPassword.toCharArray());
                    Identity issuerId = issuerIdp.getIdentity();
                    userIdp = new UsernameIdentityProvider(user.email, grailsApplication.config.gria.identity.dnDomain,
                        user.email, user.password, issuerId.getPrivateKey(),
                        issuerId.getCertificate());
                    Identity id = userIdp.getIdentity(); 
                    id = userIdp.getIdentity()
                    println id          
                    id.saveKeyStore(keystoreFile)   
                } 
                else {
                    println "Existing Keystore found..."
                    userIdp = new KeystoreIdentityProvider(user.keystoreLocation,
                            user.password.toCharArray());   
                    Identity id = userIdp.getIdentity(); 
                    id = userIdp.getIdentity()
                    println id
                    }
            
                println "Creating serviceFactory..."
            
                AxisTransport myTransport = new AxisTransport(userIdp);
            
                myTransport.setCertificateTrustValidator(new CertificateFileTrustValidator(new File(grailsApplication.config.gria.identity.trustCertificateDir)));
            
                WSDLCacheImpl myWsdlCache = new WSDLCacheImpl(myTransport);
                InvocationEngineProxyFactory pf = new InvocationEngineProxyFactory(new DefaultInvocationEngine(myTransport), myWsdlCache);

                GridClientPluginManager gcpm = new GridClientPluginManager();
                gcpm.loadPlugins();
            
                user.helperProxyFactory = new HelperProxyFactory(pf,gcpm.getHelperRegistry());
            
                user.serviceFactory = new ServiceFactory(myWsdlCache, user.helperProxyFactory); 
            
                user.subjectDN = userIdp.getIdentity().getCertificate().getSubjectDN().toString();
                
                print user.subjectDN
                
               
        }
        if(!user.hasErrors() && user.save()) {
            flash.message = "User ${user.id} created"
            redirect(action:list)
        }
        else {
            render(view:'create',model:[user:user])
        }
    }
    
    def show = {        
        def user = User.get( params.id )

        if(!user) {
            flash.message = "User not found with id ${params.id}"
            redirect(action:list)
        }
        else { return [ user : user ] }
    }
}
    